package com.tucy.logistics.security.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tucy.logistics.common.constants.RedisConstants;
import com.tucy.logistics.modules.system.captcha.mapper.SystemCaptchaMapper;
import com.tucy.logistics.security.pojo.LoginDto;
import com.tucy.logistics.common.entity.user.SystemUser;
import com.tucy.logistics.common.result.ServiceException;
import com.tucy.logistics.security.pojo.TokenDetails;
import com.tucy.logistics.security.pojo.UserDto;
import com.tucy.logistics.security.service.SystemUserService;
import com.tucy.logistics.security.mapper.SystemUserMapper;
import com.tucy.logistics.utils.RedisUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Map;

/**
* @author tucy123
* @description 针对表【system_user(用户表)】的数据库操作Service实现
* @createDate 2023-07-31 17:28:48
*/
@Service
public class SystemUserServiceImpl extends ServiceImpl<SystemUserMapper, SystemUser> implements SystemUserService {

    @Value("${rsaSecretKey.privateKey}")
    private String privateKey;

    @Value("${rsaSecretKey.publicKey}")
    private String publicKey;

    @Autowired
    private SystemCaptchaMapper systemCaptchaMapper;

    @Autowired
    RedisUtil redisUtil;

    /**
     * RSA密钥
     * @return
     */
    @SneakyThrows
    @Override
    public Map<String, String> secretKey() {
        return SaSecureUtil.rsaGenerateKeyPair();
    }

    /**
     * 系统正常注册
     * @param user
     * @return
     */
    @SneakyThrows
    @Override
    public Boolean normalRegistration(SystemUser user) {

        if (ObjectUtil.isNotEmpty(this.queryUser(user.getUsername()))){
            throw new ServiceException("账号已经注册，请重新设定");
        }
        String password = user.getPassword();

        String secretPassword = BCrypt.hashpw(password, BCrypt.gensalt());

        user.setPassword(secretPassword);

        return this.saveOrUpdate(user);
    }

    /**
     * 系统登录
     * @param dto
     * @return
     */
    @Override
    public TokenDetails login(LoginDto dto) {
        //验证码 修改为redis获取
        Object captcha = redisUtil.get(RedisConstants.logistics_captcha + dto.getKey());
        //SystemCaptcha captcha = systemCaptchaMapper.queryCaptcha(dto.getKey());
        if (ObjectUtil.isEmpty(captcha)) {
            throw new ServiceException("验证码失效");
        }
        if (!captcha.equals(dto.getCode())) {
            throw new ServiceException("验证码错误");
        }

        TokenDetails details = new TokenDetails();

        SystemUser systemUser = this.lambdaQuery().eq(SystemUser::getUsername, dto.getAccount()).one();
        if (ObjectUtil.isEmpty(systemUser)){
            throw new ServiceException("账号不存在");
        }

        boolean checkWord = BCrypt.checkpw(dto.getPassword(), systemUser.getPassword());
        if (!checkWord){
            throw new ServiceException("密码错误");
        }
        StpUtil.login(systemUser.getId());

        details.setUser(systemUser);
        details.setToken(StpUtil.getTokenValue());

        long tokenTimeout = StpUtil.getTokenTimeout();
        long currentTimeMillis = System.currentTimeMillis();
        long timeMillis = currentTimeMillis + tokenTimeout * 1000;
        details.setExpireTime(new Date(timeMillis));
        return details;
    }

    /**
     * 查询密码
     * @param username
     * @return
     */
    @Override
    public SystemUser queryUser(String username) {

        return this.lambdaQuery().eq(SystemUser::getUsername, username).one();
    }

    /**
     * 注销登录
     * @return
     */
    @Override
    public String loginOut() {

        StpUtil.logout();

        return StpUtil.getTokenValue();
    }

    /**
     * 校验登录
     * @return
     */
    @Override
    public Boolean checkLogin() {
        return StpUtil.isLogin();
    }

    /**
     * 修改密码
     * @param loginDto
     * @return
     */
    @Override
    public Boolean updatePassword(LoginDto loginDto) {

        SystemUser systemUser = this.queryUser(loginDto.getAccount());

        boolean checkWord = BCrypt.checkpw(loginDto.getPassword(), systemUser.getPassword());

        if (!checkWord){
            throw new ServiceException("原密码不正确");
        }

        systemUser.setPassword(BCrypt.hashpw(loginDto.getNewPassword(), BCrypt.gensalt()));

        return this.updateById(systemUser);
    }

    /**
     *
     * @param loginDto
     * @return
     */
    @Override
    public Boolean logOutAccount(LoginDto loginDto) {
        int i = this.baseMapper.deleteById(loginDto.getId());
        return i != 0;
    }

    /**
     * 用户查询
     * @param userDto
     * @return
     */
    @Override
    public Page<SystemUser> queryUsers(UserDto userDto) {

        Page<SystemUser> page = new Page<>(userDto.getPageNum(),userDto.getPageSize());

        QueryWrapper<SystemUser> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(ObjectUtil.isNotEmpty(userDto.getId()),SystemUser::getId,userDto.getId())
                .like(ObjectUtil.isNotEmpty(userDto.getUsername()),SystemUser::getUsername,userDto.getUsername())
                .like(ObjectUtil.isNotEmpty(userDto.getNickname()),SystemUser::getNickname,userDto.getNickname())
                .like(ObjectUtil.isNotEmpty(userDto.getMobile()),SystemUser::getMobile,userDto.getMobile())
                .like(ObjectUtil.isNotEmpty(userDto.getGender()),SystemUser::getGender,userDto.getGender())
                .like(ObjectUtil.isNotEmpty(userDto.getCity()),SystemUser::getCity,userDto.getCity())
                .like(ObjectUtil.isNotEmpty(userDto.getJob()),SystemUser::getJob,userDto.getJob())
                .eq(ObjectUtil.isNotEmpty(userDto.getRoleId()),SystemUser::getRoleId,userDto.getRoleId())
                .eq(ObjectUtil.isNotEmpty(userDto.getOrganizationId()),SystemUser::getOrganizationId,userDto.getOrganizationId());

        return this.baseMapper.selectPage(page,wrapper);
    }

    /**
     * id查询用户
     * @param userId
     * @return
     */
    @Override
    public SystemUser queryUserById(String userId) {
        return this.lambdaQuery().eq(SystemUser::getId,userId).one();
    }
}
